package com.bluemobi.framework.pay.wechat.service;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.StringUtils;
import org.xml.sax.SAXException;

import com.alibaba.fastjson.JSON;
import com.bluemobi.framework.constant.SystemConstant;
import com.bluemobi.framework.pay.wechat.common.Configure;
import com.bluemobi.framework.pay.wechat.common.PayCommonUtil;
import com.bluemobi.framework.pay.wechat.entity.UnifiedOrderReq;
import com.bluemobi.framework.pay.wechat.entity.UnifiedOrderRes;

/**
 * AAP 当支付账号为单账号支付的时候: UnifiedOrder不需要设置APPID等参数,只需在PayConstant内设置即可
 * 当支付账号为多账号支付的时候: UnifiedOrder需要设置APPID等参数。
 *
 * @author zhangyong
 * @version 1.0
 * @Date 2016-4-26 10:14
 */
public class AppPayService extends BasePayService {

	public AppPayService() throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException,
			KeyStoreException, IOException, NoSuchProviderException {
		super(Configure.UNIFIEDORDER_URL);
	}

	/**
	 * 请求支付服务
	 *
	 * @param uoreq
	 *            统一支付请求对象
	 * @return API返回的数据
	 */
	public Map<String, Object> execute(UnifiedOrderReq uoreq) {
		uoreq.setTrade_type("APP");
		Map<String, Object> resultMap = new HashMap<>();
		resultMap.put("status", SystemConstant.RETURN_STATUS_FAIL);
		try {
			if (StringUtils.isEmpty(uoreq.getKey())) {
				uoreq.setKey(Configure.APIKEY);
			}
			if (StringUtils.isEmpty(uoreq.getAppid())) {
				uoreq.setAppid(Configure.APPID);
			}
			if (StringUtils.isEmpty(uoreq.getMch_id())) {
				uoreq.setMch_id(Configure.MCH_ID);
			}
			if (StringUtils.isEmpty(uoreq.getNonce_str())) {
				uoreq.setNonce_str(PayCommonUtil.getNoncestr());
			}
			// 获取加密签名
			uoreq.setSign(PayCommonUtil.getSign(uoreq));
			if (StringUtils.isNotEmpty(uoreq.getSign())) {
				String key = uoreq.getKey();
				uoreq.setKey(null);
				// 请求预支付接口
				try {
					String responseString = sendPost(uoreq);
					try {
						UnifiedOrderRes uorres = PayCommonUtil.getObjectFromXML(responseString, UnifiedOrderRes.class);
						if (uorres.getReturn_code().equals(Configure.RETURN_CODE_SUCCESS)
								&& uorres.getResult_code().equals(Configure.RETURN_CODE_SUCCESS)) {
							// 验证签名是否正确
							if (PayCommonUtil.checkIsSignValidFromResponseStrings(uorres, key)) {
								// 判断预支付是否成功
								if (uorres.getResult_code().equals(Configure.RESULT_CODE_SUCCESS)) {
									SortedMap<String, Object> params = new TreeMap<>();
									params.put("appid", uorres.getAppid());
									params.put("key", key);
									params.put("partnerid", uorres.getMch_id());
									params.put("prepayid", uorres.getPrepay_id());
									params.put("package", "Sign=WXPay");
									params.put("noncestr", PayCommonUtil.getNoncestr());
									params.put("timestamp", System.currentTimeMillis() / 1000);
									String paySign = PayCommonUtil.getSign(params);
									params.remove("key");
									params.put("sign", paySign);
									resultMap.put("status", SystemConstant.RETURN_STATUS_SUCCESS);
									resultMap.put("data", params);
									logger.info("APP预支付返回结果：" + JSON.toJSONString(resultMap));
								} else {
									logger.error("预支付失败：" + uorres.getReturn_msg() + ";" + uorres.getErr_code() + ":"
											+ uorres.getErr_code_des() + ";原始返回数据:" + responseString);
									resultMap.put("msg", "预支付失败");
								}
							} else {
								resultMap.put("msg", "回调签名验证失败");
								logger.error("回调签名验证失败:" + responseString);
							}
						} else {
							resultMap.put("msg", "预支付失败");
							logger.error("预支付失败：" + uorres.getReturn_msg() + ";" + uorres.getErr_code() + ":"
									+ uorres.getErr_code_des() + ";原始返回数据:" + responseString);
						}
					} catch (ParserConfigurationException | IOException | SAXException e) {
						resultMap.put("msg", "验证支付回调sign异常");
						logger.error("验证支付回调sign异常:" + e.getMessage());
					}
				} catch (UnrecoverableKeyException | IOException | NoSuchAlgorithmException | KeyStoreException
						| KeyManagementException | NoSuchProviderException e) {
					resultMap.put("msg", "调用预支付接口异常");
					logger.error("调用预支付接口异常:参数" + JSON.toJSONString(uoreq) + " 错误信息:" + e.getMessage());
				}
			} else {
				resultMap.put("msg", "签名错误");
				logger.error("签名错误：无签名信息");
			}
		} catch (IllegalAccessException e) {
			resultMap.put("msg", "预支付前,签名异常");
			logger.error("预支付前,签名异常：" + e.getMessage());
		}
		return resultMap;
	}
}
